package utils

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"sync"
)

// Settings 设置管理器
type Settings struct {
	data  map[string]interface{}
	file  string
	mutex sync.RWMutex
}

// NewSettings 创建新的设置管理器
func NewSettings() *Settings {
	return &Settings{
		data: make(map[string]interface{}),
		file: "sokit-config.json",
	}
}

// Set 设置配置项
func (s *Settings) Set(section, key, value string) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	configKey := fmt.Sprintf("%s.%s", section, key)
	s.data[configKey] = value
}

// Get 获取配置项
func (s *Settings) Get(section, key, defaultValue string) string {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	configKey := fmt.Sprintf("%s.%s", section, key)
	if value, exists := s.data[configKey]; exists {
		if str, ok := value.(string); ok {
			return str
		}
	}

	return defaultValue
}

// SetInt 设置整数配置项
func (s *Settings) SetInt(section, key string, value int) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	configKey := fmt.Sprintf("%s.%s", section, key)
	s.data[configKey] = value
}

// GetInt 获取整数配置项
func (s *Settings) GetInt(section, key string, defaultValue int) int {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	configKey := fmt.Sprintf("%s.%s", section, key)
	if value, exists := s.data[configKey]; exists {
		if num, ok := value.(float64); ok {
			return int(num)
		}
		if num, ok := value.(int); ok {
			return num
		}
	}

	return defaultValue
}

// SetBool 设置布尔配置项
func (s *Settings) SetBool(section, key string, value bool) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	configKey := fmt.Sprintf("%s.%s", section, key)
	s.data[configKey] = value
}

// GetBool 获取布尔配置项
func (s *Settings) GetBool(section, key string, defaultValue bool) bool {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	configKey := fmt.Sprintf("%s.%s", section, key)
	if value, exists := s.data[configKey]; exists {
		if b, ok := value.(bool); ok {
			return b
		}
	}

	return defaultValue
}

// Load 加载配置文件
func (s *Settings) Load() error {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	// 获取配置文件路径
	configPath := s.getConfigPath()

	// 检查文件是否存在
	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		return nil // 文件不存在，使用默认设置
	}

	// 读取配置文件
	data, err := os.ReadFile(configPath)
	if err != nil {
		return fmt.Errorf("读取配置文件失败: %v", err)
	}

	// 解析JSON
	err = json.Unmarshal(data, &s.data)
	if err != nil {
		return fmt.Errorf("解析配置文件失败: %v", err)
	}

	return nil
}

// Save 保存配置文件
func (s *Settings) Save() error {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	// 获取配置文件路径
	configPath := s.getConfigPath()

	// 确保目录存在
	configDir := filepath.Dir(configPath)
	if err := os.MkdirAll(configDir, 0755); err != nil {
		return fmt.Errorf("创建配置目录失败: %v", err)
	}

	// 序列化为JSON
	data, err := json.MarshalIndent(s.data, "", "  ")
	if err != nil {
		return fmt.Errorf("序列化配置失败: %v", err)
	}

	// 写入文件
	err = os.WriteFile(configPath, data, 0644)
	if err != nil {
		return fmt.Errorf("写入配置文件失败: %v", err)
	}

	return nil
}

// getConfigPath 获取配置文件路径
func (s *Settings) getConfigPath() string {
	// 优先使用当前目录
	if _, err := os.Stat(s.file); err == nil {
		return s.file
	}

	// 使用用户配置目录
	configDir, err := os.UserConfigDir()
	if err == nil {
		return filepath.Join(configDir, "sokit", s.file)
	}

	// 使用当前目录
	return s.file
}

// GetConfigPath 获取配置文件路径
func (s *Settings) GetConfigPath() string {
	return s.getConfigPath()
}

// Clear 清除所有配置
func (s *Settings) Clear() {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	s.data = make(map[string]interface{})
}

// GetAll 获取所有配置
func (s *Settings) GetAll() map[string]interface{} {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	result := make(map[string]interface{})
	for k, v := range s.data {
		result[k] = v
	}

	return result
}

// Remove 移除配置项
func (s *Settings) Remove(section, key string) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	configKey := fmt.Sprintf("%s.%s", section, key)
	delete(s.data, configKey)
}

// Has 检查配置项是否存在
func (s *Settings) Has(section, key string) bool {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	configKey := fmt.Sprintf("%s.%s", section, key)
	_, exists := s.data[configKey]
	return exists
}

// GetSection 获取指定节的所有配置
func (s *Settings) GetSection(section string) map[string]interface{} {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	result := make(map[string]interface{})
	prefix := section + "."

	for k, v := range s.data {
		if len(k) > len(prefix) && k[:len(prefix)] == prefix {
			key := k[len(prefix):]
			result[key] = v
		}
	}

	return result
}
